In software development, it is good design practice to build applications using a large number of small and distinct modules or projects, because this promotes reuse of such building blocks, thereby improving scalability and reducing complexity of the development task, as small modules or projects are less likely to be application specific, or in other words, are more likely to be reusable.
However, a downside of having high granularity is that a large number of different modules or projects co-exist, which inter alia complicates the data integrity in terms of file location. For instance, some of the building blocks of a software project, e.g., folders or files, may be moved to another location when being reused, e.g., during project refactoring, or when being updated or otherwise amended.
This can cause problems when refactoring (parts of) an existing application, for instance when a source file comprises a reference to another source file that may have been moved to another location, or when an existing project or module has been split into smaller portions, such that some of the folders and files of the project or module have moved to a new location. A compiler typically will try and locate such a building block based on a search path, with the compiler returning an error if the building block can no longer be found in the given physical location. Upon the occurrence of such an error, the compilation process must be repaired, i.e., the search paths to the physical locations of the files must be corrected. For software development environments comprising many of such building blocks this can be a cumbersome exercise, as the developer of the corrupted compilation process usually has no knowledge of the subsequent use and the new location of the desired building blocks of the software module or project, such that a time-consuming file search must be applied to retrieve the new location of these building blocks. This task can easily become unmanageable when a software project is defined by a large number of building blocks.
In order to facilitate such a task, solutions exist that offer a level of indirection. For instance, compilation management solutions such as Imake provide mechanisms to abstract project dependencies by declaring variables that point to physical locations, in which each variable may represent a set of file paths, and use these variables when defining compilation search paths.
For instance, such a variable-based search path may take the form of BUILD_PATH=DATABASE, USER_INTERFACE, BUSINESS_LOGIC, EIGEN in which “DATABASE”, “USER_INTERFACE”, “BUSINESS_LOGIC” and “EIGEN” are the variables of the build path, with each variable representing the physical locations of a set of associated building blocks such as a file or folder, e.g., DATABASE=\u\workspace\accessor\db\; \u\workspace\db2_persistence\ in which the source files in the folders db and db2_persistence define the DATABASE part of the build path.
Nevertheless, the software project belonging to this build path may be refactored, and the search paths for a variable may change as a result. For instance, for the above example, the building block \u\workspace\accessor\db\ may be refactored into two smaller building blocks: \u\workspace\accessor-framework\db\ and u\workspace\accessor-logic\db\, such that the new value for the DATABASE variable becomes: DATABASE=\u\workspace\accessor-framework\db\; u\workspace\accessor-logic\db\; \u\workspace\db2_persistence\. This refactoring requires user intervention, e.g., because aliasing algorithms cannot cope with the change in granularity.